﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bamboo.Utils
{
    /// <summary>
    /// 去除C++源代码中的注释
    /// </summary>
    public class CppCommentFilter
    {
        /// <summary>
        /// 处理方式，1-删除注释(默认值)；2-将注释替换成空格
        /// </summary>
        public int Mode { get; set; } = 1;
        /// <summary>
        /// 处理源代码内容
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public string Handle(string input)
        {
            var output = new StringBuilder(input.Length);
            int index = 0;
            int state = 0; //1-单行注释开始；2-多行注释开始；3-字符串常量开始；4-char常量开始
            while (index < input.Length)
            {
                bool hasNextCh = index < input.Length - 1;
                char ch1 = input[index];
                char ch2 = hasNextCh ? input[index + 1] : '\0';
                if (state == 0) //初态
                {
                    if (ch1 == '/' && ch2 == '*')  //遇到多行注释开头
                    {
                        state = 2;
                        index += 2;
                        if (Mode == 2) output.Append("  ");
                    }
                    else if (ch1 == '/' && ch2 == '/')  //遇到单行注释开头
                    {
                        state = 1;
                        index += 2;
                        if (Mode == 2) output.Append("  ");
                    }
                    else if (ch1 == '\"')   //遇到字符串开头
                    {
                        output.Append(ch1);
                        state = 3;
                        index++;
                    }
                    else if (ch1 == '\'')    //遇到char常量开头
                    {
                        output.Append(ch1);
                        state = 4;
                        index += 1;
                    }
                    else if (ch1 == '\'' && ch2 == '\\') //遇到单引号+转义
                    {
                        output.Append(ch1);
                        output.Append(ch2);
                        index += 2;
                    }
                else  //其他
                {
                    output.Append(ch1);
                    index++;
                }
                }
                else if (state == 1)   //单行注释
                {
                    if (ch1 == '\n')    //遇到换行
                    {
                        state = 0;
                        output.Append("\n");
                        index++;
                    }
                    else if (ch1 == '\0')  //遇到文末
                    {
                        state = 0;
                        index++;
                    }
                    else  //其他
                    {
                        index++;
                        if (Mode == 2) output.Append(" ");
                    }
                }
                else if (state == 2)  //多行注释
                {
                    if (ch1 == '*' && ch2 == '/')  //遇到注释结尾
                    {
                        state = 0;
                        index += 2;
                        if (Mode == 2) output.Append("  ");
                    }
                    else  //其他
                    {
                        index++;
                    }
                }
                else if (state == 3)  //字符串
                {
                    if (ch1 == '\\')  //遇到转译
                    {
                        output.Append("\\");
                        output.Append(ch2);
                        index += 2;
                    }
                    else if (ch1 == '"')  //遇到字符串结尾
                    {
                        output.Append(ch1);
                        state = 0;
                        index++;
                    }
                    else  //其他
                    {
                        output.Append(ch1);
                        index++;
                    }
                }
                else if (state == 4)  //字符常量
                {
                    if (ch1 == '\\')  //遇到转译
                    {
                        output.Append("\\");
                        output.Append(ch2);
                        index += 2;
                    }
                    else if (ch1 == '\'')  //遇到结尾
                    {
                        output.Append(ch1);
                        state = 0;
                        index++;
                    }
                    else  //其他
                    {
                        output.Append(ch1);
                        index++;
                    }
                }
            }
            return output.ToString();
        }
        
    }
}
